package com.och.mrcp.core.mrcp.factory;

import com.och.mrcp.core.mrcp.model.MrcpRequest;
import com.och.mrcp.core.mrcp.model.MrcpResponse;
import com.och.mrcp.core.mrcp.model.MrcpEvent;
import com.och.mrcp.core.mrcp.model.MrcpMessage.MessageType;

/**
 * MRCP消息工厂类
 * 用于创建各种类型的MRCP消息
 * RFC 6787 - Media Resource Control Protocol Version 2 (MRCPv2)
 */
public class MrcpMessageFactory {
    
    /**
     * 创建成功响应
     */
    public static MrcpResponse createSuccessResponse(MrcpRequest request) {
        MrcpResponse response = new MrcpResponse();
        
        // 复制基本属性（安全处理null值）
        response.setResourceType(request.getResourceType());
        if (request.getResourceUri() != null) {
            response.setResourceUri(request.getResourceUri());
        }
        if (request.getChannelIdentifier() != null) {
            response.setChannelIdentifier(request.getChannelIdentifier());
        }
        if (request.getSessionId() != null) {
            response.setSessionId(request.getSessionId());
        }
        
        // 设置响应属性
        response.setMessageType(MessageType.RESPONSE);
        response.setStatusCode(MrcpResponse.StatusCode.SUCCESS);
        response.setRequestState("COMPLETE");
        response.setRequestId(request.getRequestId());
        
        // 按RFC 6787顺序添加必要的MRCP头部
        response.addHeader("Channel-Identifier", request.getChannelIdentifier());
        response.addHeader("Completion-Cause", "000 success");
        

        
        return response;
    }
    
    /**
     * 创建进行中响应
     */
    public static MrcpResponse createInProgressResponse(MrcpRequest request) {
        MrcpResponse response = new MrcpResponse();
        
        // 复制基本属性（安全处理null值）
        response.setResourceType(request.getResourceType());
        if (request.getResourceUri() != null) {
            response.setResourceUri(request.getResourceUri());
        }
        if (request.getChannelIdentifier() != null) {
            response.setChannelIdentifier(request.getChannelIdentifier());
        }
        if (request.getSessionId() != null) {
            response.setSessionId(request.getSessionId());
        }
        
        // 设置响应属性
        response.setMessageType(MessageType.RESPONSE);
        response.setStatusCode(MrcpResponse.StatusCode.SUCCESS);
        response.setRequestState("IN-PROGRESS");
        response.setRequestId(request.getRequestId());
        
        // 按RFC 6787顺序添加必要的MRCP头部
        response.addHeader("Channel-Identifier", request.getChannelIdentifier());
        
        return response;
    }
    
    /**
     * 创建失败响应
     */
    public static MrcpResponse createFailureResponse(MrcpRequest request, int statusCode, String reason) {
        MrcpResponse response = new MrcpResponse();
        
        // 复制基本属性（安全处理null值）
        response.setResourceType(request.getResourceType());
        if (request.getResourceUri() != null) {
            response.setResourceUri(request.getResourceUri());
        }
        if (request.getChannelIdentifier() != null) {
            response.setChannelIdentifier(request.getChannelIdentifier());
        }
        if (request.getSessionId() != null) {
            response.setSessionId(request.getSessionId());
        }
        
        // 设置响应属性
        response.setMessageType(MessageType.RESPONSE);
        response.setStatusCode(MrcpResponse.StatusCode.fromCode(statusCode));
        // 对于失败响应，应该使用COMPLETE状态，因为请求已完成（虽然失败了）
        response.setRequestState("COMPLETE");
        response.setRequestId(request.getRequestId());
        
        // 格式化完成原因，确保符合MRCP标准
        String formattedCause = formatCompletionCause(statusCode, reason);
        response.setCompletionCause(formattedCause);
        
        // 按RFC 6787顺序添加必要的MRCP头部
        response.addHeader("Channel-Identifier", request.getChannelIdentifier());
        response.addHeader("Completion-Cause", formattedCause);
        
        return response;
    }
    
    /**
     * 创建方法失败响应
     */
    public static MrcpResponse createMethodFailureResponse(MrcpRequest request, String reason) {
        // 参考Cairo项目：对于操作失败（如服务不可用），使用STATUS_OPERATION_FAILED (407)
        return createFailureResponse(request, 407, reason);
    }
    
    /**
     * 创建资源不可用响应
     */
    public static MrcpResponse createResourceUnavailableResponse(MrcpRequest request) {
        return createFailureResponse(request, 503, "Resource Unavailable");
    }

    /**
     * 创建RECOGNITION-COMPLETE错误事件（当发生错误时）
     * 参考Cairo项目模式
     */
    public static MrcpEvent createRecognitionCompleteErrorEvent(MrcpRequest request, String reason) {
        MrcpEvent event = new MrcpEvent(request.getResourceType(), MrcpEvent.EventType.RECOGNITION_COMPLETE);
        
        // 设置基本属性
        event.setRequestId(request.getRequestId());
        event.setRequestState("COMPLETE");
        
        // 添加Channel-Identifier
        String channelId = request.getHeader("Channel-Identifier");
        if (channelId != null) {
            event.addHeader("Channel-Identifier", channelId);
        }
        
        // 添加Completion-Cause：对于错误情况使用006 recognizer-error
        event.addHeader("Completion-Cause", "006 recognizer-error");
        
        return event;
    }
    
    /**
     * 创建不支持的方法响应
     */
    public static MrcpResponse createMethodNotImplementedResponse(MrcpRequest request) {
        return createFailureResponse(request, 501, "Method Not Implemented");
    }
    
    /**
     * 创建语音识别开始事件
     */
    public static MrcpEvent createStartOfInputEvent(MrcpRequest request) {
        MrcpEvent event = new MrcpEvent();
        
        // 复制基本属性（安全处理null值）
        event.setResourceType(request.getResourceType());
        if (request.getResourceUri() != null) {
            event.setResourceUri(request.getResourceUri());
        }
        if (request.getChannelIdentifier() != null) {
            event.setChannelIdentifier(request.getChannelIdentifier());
        }
        if (request.getSessionId() != null) {
            event.setSessionId(request.getSessionId());
        }
        
        // 设置事件属性
        event.setMessageType(MessageType.EVENT);
        event.setRequestId(request.getRequestId());
        event.setRequestState("IN-PROGRESS");
        
        // 设置事件类型
        event.setEventType(MrcpEvent.EventType.START_OF_INPUT);
        
        // 按RFC 6787顺序添加必要的MRCP头部
        event.addHeader("Channel-Identifier", request.getChannelIdentifier());
        
        return event;
    }
    
    /**
     * 创建语音识别完成事件
     */
    public static MrcpEvent createRecognitionCompleteEvent(MrcpRequest request, String result) {
        MrcpEvent event = new MrcpEvent();
        
        // 复制基本属性（安全处理null值）
        event.setResourceType(request.getResourceType());
        if (request.getResourceUri() != null) {
            event.setResourceUri(request.getResourceUri());
        }
        if (request.getChannelIdentifier() != null) {
            event.setChannelIdentifier(request.getChannelIdentifier());
        }
        if (request.getSessionId() != null) {
            event.setSessionId(request.getSessionId());
        }
        
        // 设置事件属性
        event.setMessageType(MessageType.EVENT);
        event.setRequestId(request.getRequestId());
        event.setRequestState("COMPLETE");
        
        // 设置事件类型和结果
        event.setEventType(MrcpEvent.EventType.RECOGNITION_COMPLETE);
        event.setCompletionCause("SUCCESS");
        
        // 如果有识别结果，添加到事件体
        if (result != null && !result.trim().isEmpty()) {
            event.setBody(result);
            // 添加Content-Length头（使用UTF-8字节长度）
            try {
                int contentLength = result.getBytes("UTF-8").length;
                event.addHeader("Content-Length", String.valueOf(contentLength));
            } catch (Exception e) {
                // 如果UTF-8编码失败，使用字符长度
                event.addHeader("Content-Length", String.valueOf(result.length()));
            }
        }
        
        // 按RFC 6787顺序添加必要的MRCP头部
        event.addHeader("Channel-Identifier", request.getChannelIdentifier());
        event.addHeader("Completion-Cause", "000 success");
        event.addHeader("Content-Type", "application/x-nlsml");
        
        return event;
    }
    
    /**
     * 创建语音合成开始事件
     */
    public static MrcpEvent createSpeakStartEvent(MrcpRequest request) {
        MrcpEvent event = new MrcpEvent();
        
        // 复制基本属性（安全处理null值）
        event.setResourceType(request.getResourceType());
        if (request.getResourceUri() != null) {
            event.setResourceUri(request.getResourceUri());
        }
        if (request.getChannelIdentifier() != null) {
            event.setChannelIdentifier(request.getChannelIdentifier());
        }
        if (request.getSessionId() != null) {
            event.setSessionId(request.getSessionId());
        }
        
        // 设置事件属性
        event.setMessageType(MessageType.EVENT);
        event.setRequestId(request.getRequestId());
        event.setRequestState("IN-PROGRESS");
        
        // 设置事件类型（修正为SPEAK_START）
        event.setEventType(MrcpEvent.EventType.SPEAK_START);
        
        // 添加必要的MRCP头部
        event.addHeader("Channel-Identifier", request.getChannelIdentifier());
        
        return event;
    }
    
    /**
     * 创建语音合成完成事件
     */
    public static MrcpEvent createSpeakCompleteEvent(MrcpRequest request) {
        MrcpEvent event = new MrcpEvent();
        
        // 复制基本属性（安全处理null值）
        event.setResourceType(request.getResourceType());
        if (request.getResourceUri() != null) {
            event.setResourceUri(request.getResourceUri());
        }
        if (request.getChannelIdentifier() != null) {
            event.setChannelIdentifier(request.getChannelIdentifier());
        }
        if (request.getSessionId() != null) {
            event.setSessionId(request.getSessionId());
        }
        
        // 设置事件属性
        event.setMessageType(MessageType.EVENT);
        event.setRequestId(request.getRequestId());
        event.setRequestState("COMPLETE");
        
        // 设置事件类型
        event.setEventType(MrcpEvent.EventType.SPEAK_COMPLETE);
        event.setCompletionCause("SUCCESS");
        
        // 添加必要的MRCP头部
        event.addHeader("Channel-Identifier", request.getChannelIdentifier());
        event.addHeader("Completion-Cause", "000 normal");
        
        return event;
    }
    
    /**
     * 创建输入超时事件
     */
    public static MrcpEvent createInputTimeoutEvent(MrcpRequest request) {
        MrcpEvent event = new MrcpEvent();
        
        // 复制基本属性（安全处理null值）
        event.setResourceType(request.getResourceType());
        if (request.getResourceUri() != null) {
            event.setResourceUri(request.getResourceUri());
        }
        if (request.getChannelIdentifier() != null) {
            event.setChannelIdentifier(request.getChannelIdentifier());
        }
        if (request.getSessionId() != null) {
            event.setSessionId(request.getSessionId());
        }
        
        // 设置事件属性
        event.setMessageType(MessageType.EVENT);
        event.setRequestId(request.getRequestId());
        event.setRequestState("IN-PROGRESS");
        
        // 设置事件类型
        event.setEventType(MrcpEvent.EventType.RECOGNITION_COMPLETE);
        event.setCompletionCause("NO-INPUT-TIMEOUT");
        
        // 添加必要的MRCP头部
        event.addHeader("Channel-Identifier", request.getChannelIdentifier());
        
        return event;
    }
    
    /**
     * 创建无匹配事件
     */
    public static MrcpEvent createNoMatchEvent(MrcpRequest request) {
        MrcpEvent event = new MrcpEvent();
        
        // 复制基本属性（安全处理null值）
        event.setResourceType(request.getResourceType());
        if (request.getResourceUri() != null) {
            event.setResourceUri(request.getResourceUri());
        }
        if (request.getChannelIdentifier() != null) {
            event.setChannelIdentifier(request.getChannelIdentifier());
        }
        if (request.getSessionId() != null) {
            event.setSessionId(request.getSessionId());
        }
        
        // 设置事件属性
        event.setMessageType(MessageType.EVENT);
        event.setRequestId(request.getRequestId());
        event.setRequestState("COMPLETE");
        
        // 设置事件类型
        event.setEventType(MrcpEvent.EventType.RECOGNITION_COMPLETE);
        event.setCompletionCause("NO-MATCH");
        
        // 添加必要的MRCP头部
        event.addHeader("Channel-Identifier", request.getChannelIdentifier());
        
        return event;
    }
    
    /**
     * 创建通用事件
     */
    public static MrcpEvent createGenericEvent(MrcpRequest request, String eventName, String state) {
        MrcpEvent event = new MrcpEvent();
        
        // 复制基本属性（安全处理null值）
        event.setResourceType(request.getResourceType());
        if (request.getResourceUri() != null) {
            event.setResourceUri(request.getResourceUri());
        }
        if (request.getChannelIdentifier() != null) {
            event.setChannelIdentifier(request.getChannelIdentifier());
        }
        if (request.getSessionId() != null) {
            event.setSessionId(request.getSessionId());
        }
        
        // 设置事件属性
        event.setMessageType(MessageType.EVENT);
        event.setRequestId(request.getRequestId());
        event.setRequestState(state);
        
        // 根据事件名称设置事件类型
        try {
            event.setEventType(MrcpEvent.EventType.fromString(eventName));
        } catch (IllegalArgumentException e) {
            // 如果事件名称不匹配预定义类型，使用START_OF_INPUT作为默认值
            event.setEventType(MrcpEvent.EventType.START_OF_INPUT);
        }
        
        // 添加必要的MRCP头部
        event.addHeader("Channel-Identifier", request.getChannelIdentifier());
        
        return event;
    }
    
    /**
     * 格式化完成原因，确保符合MRCP标准
     * RFC 6787: Completion-Cause应该是数字代码加可选描述
     * 格式: "CODE description"
     */
    private static String formatCompletionCause(int statusCode, String reason) {
        if (reason == null || reason.trim().isEmpty()) {
            return statusCode + " error";
        }
        
        // 根据Cairo项目和MRCP标准的completion-cause代码
        switch (statusCode) {
            case 200:
                return "000 success";
            case 407: // STATUS_OPERATION_FAILED - Cairo项目中用于操作失败
                // 根据错误原因返回适当的completion-cause
                if (reason != null) {
                    if (reason.contains("Recognition failed") || 
                        reason.contains("Voice Service") || 
                        reason.contains("unavailable") ||
                        reason.contains("ASR session") ||
                        reason.contains("recognizer") ||
                        reason.contains("Aliyun")) {
                        return "006 recognizer-error"; // Cairo: (short) 6, "recognizer-error"
                    }
                }
                return "006 recognizer-error"; // 默认为识别器错误
            case 501: // STATUS_SERVER_INTERNAL_ERROR
                return "006 recognizer-error";
            case 400:
            case 401:
            case 403:
            case 404:
            case 405:
            case 408:
            case 500:
            default:
                return "006 recognizer-error";
        }
    }

}
